(() => {
  let body = document.body
  body.innerHTML = '天王盖地虎'
  // 布尔值 boolean
  let isDone: boolean = false
  isDone = true
  isDone = !1
  // isDone = 1 报错

  // 数字 number
  let userAge: number = 12
  userAge = 13

  // 字符串 string
  let userName: string = 'Jhon'
  userName = 'Bob'

  // undefined 和 null
  // TypeScript 里，undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null。 它们的本身的类型用处不是很大
  let u: undefined = undefined
  let n: null = null

  // 数字 Array
  let userList: string[] = ['jhon', 'bob']
  let numList: Array<number> = [1, 2, 3, 4, 5]
  numList.push(12)

  // 元组 Tuple
  // 元组类型允许表示一个已知元素数量和类型的数组，各元素的类型不必相同。 比如，你可以定义一对值分别为 string 和 number 类型的元组。
  let tuple1: [string, number]
  tuple1 = ['Jhon', 12]
  // tuple1 = [12, 'Jhon'] // Error
  // console.log(tuple1[0].substring(1))
  // console.log(tuple1[1].substring(1))  // Error

  // 枚举 enum
  enum Color { Red, Green, Blue }
  let likeColor: Color = Color.Green
  console.log(likeColor, Color.Red, Color.Blue)

  enum Color1 { Red = 1, Green, Blue }
  enum Color2 { Red = 2, Green = 2, Blue = 9 }

  let colorName: string = Color2[9]
  console.log(colorName)

  // any 任意
  // --

  // void 
  // 某种程度上来说，void 类型像是与 any 类型相反，它表示没有任何类型。 当一个函数没有返回值时，你通常会见到其返回值类型是 void
  function fn(): void {
    console.log('func fn()')
    // return undefined
    // return null
    // return 1 // Error
  }
  // 声明一个 void 类型的变量没有什么大用，因为你只能为它赋予 undefined 和 null

  // object 
  // object 表示非原始类型，也就是除 number，string，boolean之外的类型。使用 object 类型，就可以更好的表示像 Object.create 这样的 API。
  function fn1(obj: object): object {
    return {}
    // return undefined
    // return null
  }
  console.log(fn1(new String('asd')))
  // console.log(fn1('111')) // Error

  // 联合类型
  function toStr(param: number | string): string {
    return param.toString()
  }

  // function getLen(param: number | string): number {
  //   if (param.length) {
  //     return param.length //这里报错了   所以用了类型断言的方法实现本方法
  //   } else {
  //     return param.toString().length
  //   }
  // }

  // 类型断言
  // 通过类型断言这种方式可以告诉编译器，“相信我，我知道自己在干什么”。 类型断言好比其它语言里的类型转换，但是不进行特殊的数据检查和解构。 它没有运行时的影响，只是在编译阶段起作用。 TypeScript 会假设你，程序员，已经进行了必须的检查。
  // 类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法
  /* 需求: 定义一个函数得到一个字符串或者数值数据的长度 */
  function getLen(param: number | string): number {
    if ((<string>param).length) {
      return (param as string).length
    } else {
      return XMLDocument.toString().length
    }
  }

  // 类型推断
  // --
})()